package net.ib.mtalk.ui.attachment.emoticon;

import net.ib.mtalk.R;
import net.ib.mtalk.ui.widget.FlingStopGallery;
import net.ib.mtalk.util.Dip;
import net.ib.mtalk.util.MTalkLogWriter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.GridView;
import android.widget.PopupWindow;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;

public class EmoticonIme {
	
	private EditText mTargetEditText = null;
	private EmoticonGalleryAdater mGalleryAdapter = null;
	private PopupWindow mPopup;

	private RadioGroup mRadioGroup;
	private FlingStopGallery mGallery;

	/**
	 * 이모티콘 입력을 위한 창을 만든다. 창은 사용자의 조작에 의해 지정된 EditText에 이모티콘을 입력한다.
	 * @param context 호출자의 context
	 * @param mTargetEditText 이 창을 통해 편집하고자 하는 대상
	 * @return 만들어진 창의 객체
	 */
	public PopupWindow create(Context context, int width, int height, EditText editText) {
		// 이 팝업창의 편집 대상이 되는 EditText를 기억해두자.
		this.mTargetEditText = editText;

		LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		View layout = inflater.inflate(R.layout.layout_emoticon, null);
		
		mRadioGroup = (RadioGroup) layout.findViewById(R.id.emoticonPages);
		mRadioGroup.setOnCheckedChangeListener(new OnCheckedChangeListener() {
			@Override
			public void onCheckedChanged(RadioGroup group, int checkedId) {
				int galleryIdx = 0;
				switch (checkedId) {
				case R.id.emoticonPage00:
					galleryIdx = 0;
					break;
				case R.id.emoticonPage01:
					galleryIdx = 1;
					break;
				case R.id.emoticonPage02:
					galleryIdx = 2;
					break;
				case R.id.emoticonPage03:
					galleryIdx = 3;
					break;
				case R.id.emoticonPage04:
					galleryIdx = 4;
					break;
				default:
					group.check(R.id.emoticonPage00);
					break;
				}
				if (mGallery.getSelectedItemId() != galleryIdx) {	// 라디오 버튼-갤러리 간의 race condition을 막기 위한 체크
					mGallery.setSelection(galleryIdx);
				}
				return;
			}
		});
		mGallery = (FlingStopGallery) layout.findViewById(R.id.emoticonGallery);	// 실제로는 FlingStopGallery를 쓰고 있다.
		mGallery.setOnItemSelectedListener(new OnItemSelectedListener() {

			@Override
			public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
				int checkIdx = 0;
				switch (position) {
				case 0:
					checkIdx = R.id.emoticonPage00;
					break;
				case 1:
					checkIdx = R.id.emoticonPage01;
					break;
				case 2:
					checkIdx = R.id.emoticonPage02;
					break;
				case 3:
					checkIdx = R.id.emoticonPage03;
					break;
				case 4:
					checkIdx = R.id.emoticonPage04;
					break;
				default:
					mGallery.setSelection(0);
					break;
				}
				if (mRadioGroup.getCheckedRadioButtonId() != checkIdx) {	// 라디오 버튼-갤러리 간의 race condition을 막기 위한 체크
					mRadioGroup.check(checkIdx);
				}
			}

			@Override
			public void onNothingSelected(AdapterView<?> parent) {
				if (mGallery.getSelectedItemId() != 0) {	// 라디오 버튼-갤러리 간의 race condition을 막기 위한 체크
					mGallery.setSelection(0);
				}
			}
		});
		mGalleryAdapter = new EmoticonGalleryAdater(context);
		mGallery.setAdapter(mGalleryAdapter);
		
		// 팝업창 객체 생성
		mPopup = new PopupWindow(layout, width, height);
		mPopup.setOutsideTouchable(true);
		mPopup.setTouchable(true);

		return mPopup;
	}

	/**
	 * 갤러리의 원소를 위한 어댑터.
	 * 이 안에서 정의해주는 그리드가 터치 이벤트 처리를 투과하거나 막아서 이모티콘 페이지의 사용자 동작을 하게 만든다.
	 * @author Arngard
	 *
	 */
	protected class EmoticonGalleryAdater extends BaseAdapter {
		
		protected Context mContext;
		protected View mView = null;
		
		protected View[] mViewHolders = new View[RichString.pageTable.length];
		
		float memXForCancelClick = 0;
		float memYForCancelClick = 0;
		float curXForCancelClick = 0;
		float curYForCancelClick = 0;

		public EmoticonGalleryAdater(Context context) {
			mContext = context;
		}

		@Override
		public int getCount() {
			return mViewHolders.length;
		}

		@Override
		public Object getItem(int position) {
			return mViewHolders[position];
		}

		@Override
		public long getItemId(int position) {
			return position;
		}
		
		@Override
		public boolean hasStableIds() {
			return true;
		}
		
		/** 뷰 내용을 위한 데이터 캐시 */
		EmoticonGridAdapter[] emoticonGridAdapterHolder;

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			View reVal;
			if (convertView == null) {
				LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
				reVal = inflater.inflate(R.layout.gallery_element_emoticon, null);
			} else {
				reVal = convertView;
			}
			
			GridView g = (GridView) reVal.findViewById(R.id.emoticonGrid);
			try {
				EmoticonGridAdapter eadt = (EmoticonGridAdapter) g.getAdapter();
				if (eadt.getPage() != position) {
					buildNewGrid(g, position);	// 있긴 있는데 다른 페이지
				}
			} catch (Exception e) {
				buildNewGrid(g, position);	// 없엉
			}

			mViewHolders[position] = reVal;	// 기억해주기
			return reVal;
		}
		
		/**
		 * Called by {@link #getView(int, View, ViewGroup)}.
		 * @param g
		 * @param position
		 */
		private void buildNewGrid(GridView g, int position) {
			if (emoticonGridAdapterHolder == null) {
				emoticonGridAdapterHolder = new EmoticonGridAdapter[RichString.pageTable.length];
			}
			if (emoticonGridAdapterHolder[position] == null) {
				emoticonGridAdapterHolder[position] = new EmoticonGridAdapter(mContext, position, g, mTargetEditText);
				emoticonGridAdapterHolder[position].setSize((int)Dip.toPixel(30));
			}
			g.setAdapter(emoticonGridAdapterHolder[position]);
			
			g.setOnTouchListener(new OnTouchListener() {
				float memX = 0;	float memY = 0;
				float dx = 0;	float dy = 0;
				
				@Override
				public boolean onTouch(View v, MotionEvent event) {
					switch(event.getAction()){
					case MotionEvent.ACTION_DOWN:
						// 기준점을 재계산. 여기서는 절대좌표 기준으로 생각해야 할 것 같다.
						memX = event.getRawX();
						memY = event.getRawY();
						
						// 갤러리에도 이벤트를 전달해서 함께 처리되게 한다.
						mGallery.onTouchEvent(event);
						break;
					case MotionEvent.ACTION_MOVE:
						// 변위를 도출하고
						dx = event.getRawX() - memX;
						dy = event.getRawY() - memY;
						// 기준점을 재계산.
						memX = event.getRawX();
						memY = event.getRawY();
						
						if (Math.abs(dy) < Math.abs(dx)) {	// x축 변위가 더 크면 가로 방향 움직임이다.
							// 갤러리에 이벤트를 전달
							mGallery.onTouchEvent(event);
						} else {
							// 세로 방향 움직임은 그냥 흘려 보내서 그리드가 처리하게 한다.
						}
						break;
					case MotionEvent.ACTION_UP:
					case MotionEvent.ACTION_CANCEL:
						// 기준점을 리셋
						memX = 0;
						memY = 0;

						// 갤러리와 그리드 모두 최종적으로는 터치 업을 받아야 한다.
						// 여기에서는 변위에 무관하게 터치 업을 무조건 각자에게 전달한다.
						mGallery.onTouchEvent(event);
					}
					return false;
				}           
		    });
		}
		
	}	// end of "class EmoticonGalleryAdater"
	
}
